<template>
  <page-header-wrapper content="高级表单常见于一次性输入和提交大批量数据的场景">
    <a-card class="card" title="仓库管理">
      <repository-form ref="repository" :showSubmit="false" />
    </a-card>
    <a-card class="card" title="任务管理">
      <task-form ref="task" :showSubmit="false" />
    </a-card>

    <!-- table -->
    <a-card>
      <a-table
        rowKey="key"
        :columns="columns"
        :dataSource="data"
        :pagination="false"
        :loading="memberLoading"
      >
        <template
          v-for="(col, i) in ['name', 'workId', 'department']"
          :slot="col"
          slot-scope="text, record"
        >
          <a-input
            :key="col"
            v-if="record.editable"
            style="margin: -5px 0"
            :value="text"
            :placeholder="columns[i].title"
            @change="(e) => handleChange(e.target.value, record.key, col)"
          />
          <template v-else>{{ text }}</template>
        </template>
        <template slot="operation" slot-scope="text, record">
          <template v-if="record.editable">
            <span v-if="record.isNew">
              <a @click="saveRow(record)">添加</a>
              <a-divider type="vertical" />
              <a-popconfirm
                title="是否要删除此行？"
                @confirm="remove(record.key)"
              >
                <a>删除</a>
              </a-popconfirm>
            </span>
            <span v-else>
              <a @click="saveRow(record)">保存</a>
              <a-divider type="vertical" />
              <a @click="cancel(record.key)">取消</a>
            </span>
          </template>
          <span v-else>
            <a @click="toggle(record.key)">编辑</a>
            <a-divider type="vertical" />
            <a-popconfirm
              title="是否要删除此行？"
              @confirm="remove(record.key)"
            >
              <a>删除</a>
            </a-popconfirm>
          </span>
        </template>
      </a-table>
      <a-button
        style="width: 100%; margin-top: 16px; margin-bottom: 8px"
        type="dashed"
        icon="plus"
        @click="newMember"
        >新增成员
      </a-button>
    </a-card>

    <a-card class="card" title="QuillEditor">
      <QuillEditor @change="onEditorChange" />
    </a-card>

    <a-card class="card" title="TinymceEditor">
      <TinymceEditor />
    </a-card>

    <!-- fixed footer toolbar -->
    <footer-tool-bar :is-mobile="isMobile" :collapsed="sideCollapsed">
      <span class="popover-wrapper">
        <a-popover
          title="表单校验信息"
          overlayClassName="antd-pro-pages-forms-style-errorPopover"
          trigger="click"
          :getPopupContainer="(trigger) => trigger.parentNode"
        >
          <template slot="content">
            <li
              v-for="item in errors"
              :key="item.key"
              @click="scrollToField(item.key)"
              class="antd-pro-pages-forms-style-errorListItem"
            >
              <a-icon
                type="cross-circle-o"
                class="antd-pro-pages-forms-style-errorIcon"
              />
              <div class="">{{ item.message }}</div>
              <div class="antd-pro-pages-forms-style-errorField">
                {{ item.fieldLabel }}
              </div>
            </li>
          </template>
          <span
            class="antd-pro-pages-forms-style-errorIcon"
            v-if="errors.length > 0"
          >
            <a-icon type="exclamation-circle" />{{ errors.length }}
          </span>
        </a-popover>
      </span>
      <a-button type="primary" @click="validate" :loading="loading"
        >提交
      </a-button>
    </footer-tool-bar>
  </page-header-wrapper>
</template>

<script>
import RepositoryForm from "./RepositoryForm";
import TaskForm from "./TaskForm";
import { FooterToolBar, QuillEditor, TinymceEditor } from "@/components";
import { baseMixin } from "@/store/mixin/app-mixin";

const fieldLabels = {
  name: "仓库名",
  url: "仓库域名",
  owner: "仓库管理员",
  approver: "审批人",
  dateRange: "生效日期",
  type: "仓库类型",
  name2: "任务名",
  url2: "任务描述",
  owner2: "执行人",
  approver2: "责任人",
  dateRange2: "生效日期",
  type2: "任务类型",
};

export default {
  name: "AdvancedForm",
  mixins: [baseMixin],
  components: {
    FooterToolBar,
    RepositoryForm,
    TaskForm,
    QuillEditor,
    TinymceEditor,
  },
  data() {
    return {
      loading: false,
      memberLoading: false,

      // table
      columns: [
        {
          title: "成员姓名",
          dataIndex: "name",
          key: "name",
          width: "20%",
          scopedSlots: { customRender: "name" },
        },
        {
          title: "工号",
          dataIndex: "workId",
          key: "workId",
          width: "20%",
          scopedSlots: { customRender: "workId" },
        },
        {
          title: "所属部门",
          dataIndex: "department",
          key: "department",
          width: "40%",
          scopedSlots: { customRender: "department" },
        },
        {
          title: "操作",
          key: "action",
          scopedSlots: { customRender: "operation" },
        },
      ],
      data: [
        {
          key: "1",
          name: "小明",
          workId: "001",
          editable: false,
          department: "行政部",
        },
        {
          key: "2",
          name: "李莉",
          workId: "002",
          editable: false,
          department: "IT部",
        },
        {
          key: "3",
          name: "王小帅",
          workId: "003",
          editable: false,
          department: "财务部",
        },
      ],

      errors: [],
    };
  },
  methods: {
    handleSubmit(e) {
      e.preventDefault();
    },
    newMember() {
      const length = this.data.length;
      this.data.push({
        key:
          length === 0
            ? "1"
            : (parseInt(this.data[length - 1].key) + 1).toString(),
        name: "",
        workId: "",
        department: "",
        editable: true,
        isNew: true,
      });
    },
    remove(key) {
      const newData = this.data.filter((item) => item.key !== key);
      this.data = newData;
    },
    saveRow(record) {
      this.memberLoading = true;
      const { key, name, workId, department } = record;
      if (!name || !workId || !department) {
        this.memberLoading = false;
        this.$message.error("请填写完整成员信息。");
        return;
      }
      // 模拟网络请求、卡顿 800ms
      new Promise((resolve) => {
        setTimeout(() => {
          resolve({ loop: false });
        }, 800);
      }).then(() => {
        const target = this.data.find((item) => item.key === key);
        target.editable = false;
        target.isNew = false;
        this.memberLoading = false;
      });
    },
    toggle(key) {
      const target = this.data.find((item) => item.key === key);
      target._originalData = { ...target };
      target.editable = !target.editable;
    },
    getRowByKey(key, newData) {
      const data = this.data;
      return (newData || data).find((item) => item.key === key);
    },
    cancel(key) {
      const target = this.data.find((item) => item.key === key);
      Object.keys(target).forEach((key) => {
        target[key] = target._originalData[key];
      });
      target._originalData = undefined;
    },
    handleChange(value, key, column) {
      const newData = [...this.data];
      const target = newData.find((item) => key === item.key);
      if (target) {
        target[column] = value;
        this.data = newData;
      }
    },

    // 最终全页面提交
    validate() {
      const {
        $refs: { repository, task },
        $notification,
      } = this;
      const repositoryForm = new Promise((resolve, reject) => {
        repository.form.validateFields((err, values) => {
          if (err) {
            reject(err);
            return;
          }
          resolve(values);
        });
      });
      const taskForm = new Promise((resolve, reject) => {
        task.form.validateFields((err, values) => {
          if (err) {
            reject(err);
            return;
          }
          resolve(values);
        });
      });

      // clean this.errors
      this.errors = [];
      Promise.all([repositoryForm, taskForm])
        .then((values) => {
          $notification.info({
            message: "Received values of form:",
            description: JSON.stringify(values),
          });
        })
        .catch(() => {
          const errors = Object.assign(
            {},
            repository.form.getFieldsError(),
            task.form.getFieldsError()
          );
          const tmp = { ...errors };
          this.errorList(tmp);
        });
    },
    errorList(errors) {
      if (!errors || errors.length === 0) {
        return;
      }
      this.errors = Object.keys(errors)
        .filter((key) => errors[key])
        .map((key) => ({
          key: key,
          message: errors[key][0],
          fieldLabel: fieldLabels[key],
        }));
    },
    scrollToField(fieldKey) {
      const labelNode = document.querySelector(`label[for="${fieldKey}"]`);
      if (labelNode) {
        labelNode.scrollIntoView(true);
      }
    },
    onEditorChange(html) {
      console.log("onEditorChange ", html);
    },
  },
};
</script>

<style lang="less" scoped>
.card {
  margin-bottom: 24px;
}
.popover-wrapper {
  /deep/ .antd-pro-pages-forms-style-errorPopover .ant-popover-inner-content {
    min-width: 256px;
    max-height: 290px;
    padding: 0;
    overflow: auto;
  }
}
.antd-pro-pages-forms-style-errorIcon {
  user-select: none;
  margin-right: 24px;
  color: #f5222d;
  cursor: pointer;
  i {
    margin-right: 4px;
  }
}
.antd-pro-pages-forms-style-errorListItem {
  padding: 8px 16px;
  list-style: none;
  border-bottom: 1px solid #e8e8e8;
  cursor: pointer;
  transition: all 0.3s;

  &:hover {
    background: #e6f7ff;
  }
  .antd-pro-pages-forms-style-errorIcon {
    float: left;
    margin-top: 4px;
    margin-right: 12px;
    padding-bottom: 22px;
    color: #f5222d;
  }
  .antd-pro-pages-forms-style-errorField {
    margin-top: 2px;
    color: rgba(0, 0, 0, 0.45);
    font-size: 12px;
  }
}
</style>